/*
 * VimL CLI调试器 - 独立调试器程序
 *
 * 使用方法:
 *   vimlc_debug <script.vim>
 *   vimlc_debug -d <script.vim>  # 调试模式
 *   vimlc_debug --ast <script.vim>  # 显示AST
 *   vimlc_debug --help         # 显示帮助
 */

#include <iostream>
#include <fstream>
#include <memory>
#include <getopt.h>

#include "viml/vm.h"
#include "viml/compiler.h"
#include "viml/debugger.h"
#include "viml/debugger_cli.h"

using namespace viml;

void print_usage(const char* program_name) {
    std::cout << "VimL CLI调试器 v1.0\n\n";
    std::cout << "用法: " << program_name << " [选项] <VimL脚本文件>\n\n";
    std::cout << "选项:\n";
    std::cout << "  -d, --debug     启用调试模式\n";
    std::cout << "  -a, --ast      显示抽象语法树\n";
    std::cout << "  -h, --help     显示此帮助信息\n\n";
    std::cout << "示例:\n";
    std::cout << "  " << program_name << " example/hello.vim\n";
    std::cout << "  " << program_name << " -d debug_test.vim\n";
    std::cout << "  " << program_name << " --ast example/hello.vim\n";
}

void print_version() {
    std::cout << "VimL CLI调试器 v1.0\n";
    std::cout << "Copyright (c) 2024 VimL Project\n";
}

int main(int argc, char* argv[]) {
    bool debug_mode = false;
    bool show_ast = false;
    std::string filename;

    // 简化的命令行参数解析
    int opt;
    static struct option long_options[] = {
        {"debug", no_argument, 0, 'd'},
        {"ast", no_argument, 0, 'a'},
        {"help", no_argument, 0, 'h'},
        {"version", no_argument, 0, 'v'},
        {0, 0, 0, 0}
    };

    while ((opt = getopt_long(argc, argv, "da:hv", long_options, nullptr)) != -1) {
        switch (opt) {
            case 'd':
                debug_mode = true;
                break;
            case 'a':
                show_ast = true;
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
            case 'v':
                print_version();
                return 0;
            default:
                print_usage(argv[0]);
                return 1;
        }
    }

    if (optind >= argc) {
        std::cerr << "错误: 缺少VimL脚本文件\n";
        print_usage(argv[0]);
        return 1;
    }

    filename = argv[optind];

    // 检查文件是否存在
    std::ifstream file(filename);
    if (!file.is_open()) {
        std::cerr << "错误: 无法打开文件 '" << filename << "'\n";
        return 1;
    }

    try {
        // 读取源代码
        std::string source((std::istreambuf_iterator<char>(file)),
                           std::istreambuf_iterator<char>());

        // 创建虚拟机和编译器
        auto vm = std::make_shared<VM>();
        auto compiler = std::make_unique<Compiler>();

        std::cout << "正在编译文件: " << filename << "...\n";

        // 编译源代码
        auto bytecode = compiler->compile(source, filename);
        if (!bytecode) {
            std::cerr << "错误: 编译失败\n";
            return 1;
        }

        std::cout << "编译成功！指令数: " << bytecode->instruction_count()
                  << ", 常量数: " << bytecode->constant_count() << "\n";

        if (show_ast) {
            std::cout << "\n=== 抽象语法树 (AST) ===\n";
            // 这里需要访问AST并显示
            std::cout << "AST显示功能需要编译器支持\n";
            return 0;
        }

        if (debug_mode) {
            std::cout << "\n=== 启动CLI调试器 ===\n";

            // 创建调试器
            auto debugger = std::make_shared<Debugger>(vm);
            auto debug_info = std::make_shared<DebugInfo>(filename);
            debug_info->load_source_file();

            // 建立行号映射
            for (size_t pc = 0; pc < bytecode->instruction_count(); ++pc) {
                int line = bytecode->get_line_number(pc);
                if (line > 0) {
                    debug_info->add_line_mapping(line, pc);
                }
            }

            debugger->set_debug_info(debug_info);
            vm->set_debugger(debugger);
            vm->set_debug_mode(true);

            // 创建CLI调试器
            auto cli = std::make_unique<DebuggerCLI>(vm, debugger, debug_info);
            cli->load_file(filename);

            // 设置一些初始断点用于测试
            std::cout << "设置测试断点...\n";
            size_t bp1 = debugger->set_breakpoint(2);  // let x = 42
            size_t bp2 = debugger->set_breakpoint(4);  // echo 语句
            std::cout << "设置断点 " << bp1 << " 在第 2 行\n";
            std::cout << "设置断点 " << bp2 << " 在第 4 行\n";

            // 启动调试器
            debugger->start();

            std::cout << "\n=== 开始交互式调试 ===\n";
            std::cout << "程序已加载，可以使用 'run' 开始执行，或使用 'step' 单步调试\n";
            std::cout << "使用 'continue' 继续执行到下一个断点\n";

            int result = cli->run_interactive();

            // 如果用户选择了run、continue或step，则执行字节码
            if (cli->should_execute_program()) {
                std::cout << "\n=== 开始执行程序 ===\n";

                // 重置调试器状态
                debugger->start();

                if (cli->should_step_execute_program()) {
                    // 单步执行模式
                    std::cout << "执行一条指令...\n";
                    // 执行一条指令后暂停
                    // 这里需要实现单步执行逻辑
                    // 暂时执行完整程序，后续优化为真正的单步执行
                    auto exec_result = vm->execute(bytecode);
                    std::cout << "\n程序执行完成，结果: " << exec_result.to_string() << "\n";

                    // 清除单步执行标志
                    cli->set_should_step_execute(false);

                    // 如果还有断点未触发，重新进入调试模式
                    std::cout << "\n=== 重新进入调试模式 ===\n";
                    return cli->run_interactive();
                } else {
                    // 完整执行模式（run/continue）
                    std::cout << "继续执行程序...\n";
                    auto exec_result = vm->execute(bytecode);
                    std::cout << "\n程序执行完成，结果: " << exec_result.to_string() << "\n";
                }
            }

            return result;
        } else {
            std::cout << "\n=== 直接执行模式 ===\n";
            std::cout << "使用 -d 选项进入调试模式\n";

            // 直接执行字节码
            auto result = vm->execute(bytecode);
            std::cout << "\n执行完成，结果: " << result.to_string() << "\n";
            return 0;
        }

    } catch (const std::exception& e) {
        std::cerr << "错误: " << e.what() << "\n";
        return 1;
    }
}